package com.changgou.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.goods.feign.SkuFeign;
import com.changgou.goods.pojo.Sku;
import com.changgou.search.dao.SkuEsMapper;
import com.changgou.search.pojo.SkuInfo;
import com.changgou.search.service.SkuService;
import entity.Result;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 搜索微服务业务实现层
 *
 * @author zhengjd
 * @date 2020/5/9 21:30
 */
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Service
public class SkuServiceImpl implements SkuService {

    @Autowired
    SkuFeign skuFeign;

    @Autowired
    SkuEsMapper skuEsMapper;

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    SearchResultMapperImpl searchResultMapper;

    /**
     * 导入sku数据到es中
     */
    @Override
    public void importSku() {
        //查询状态为1的sku数据
        Result<List<Sku>> skuListResult = skuFeign.findByStatus("1");
        //将数据转成search.sku
        List<SkuInfo> skuInfos = JSON.parseArray(JSON.toJSONString(skuListResult.getData()), SkuInfo.class);
        //规格数据的导入，将spec转换为map，再设置到skuInfo中
        for (SkuInfo skuInfo : skuInfos) {
            Map<String, Object> specMap = JSON.parseObject(skuInfo.getSpec());
            skuInfo.setSpecMap(specMap);
        }
        skuEsMapper.saveAll(skuInfos);
    }

    /**
     * 搜索
     *
     * @param searchMap
     * @return
     */
    @Override
    public Map search(Map<String, String> searchMap) {

        //1.获取关键字的值
        String keywords = searchMap.get("keywords");
        if (StringUtils.isEmpty(keywords)) {
            //设置一个默认值
            keywords = "华为";
        }
        //2.创建查询对象的构建对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        //3.设置查询的条件
        //设置分组条件  商品分类(聚合)
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuCategorygroup").field("categoryName").size(50));
        //设置分组条件  品牌分类（聚合）
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuBrandgroup").field("brandName").size(50));
        //设置分组条件  规格参数分类
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("skuSpecgroup").field("spec.keyword").size(100));
        //nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name",keywords));
        //设置主关键字查询
        nativeSearchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery(keywords, "name", "brandName", "categoryName"));
        //添加多条件查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(searchMap.get("brand"))) {
            //品牌条件不为空
            boolQueryBuilder.filter(QueryBuilders.termQuery("brandName", searchMap.get("brand")));
        }
        if (!StringUtils.isEmpty(searchMap.get("category"))) {
            //分类条件不为空
            boolQueryBuilder.filter(QueryBuilders.termQuery("categoryName", searchMap.get("category")));
        }
        //规格过滤查询  前端格式：spec_XXX:'4G'
        for (String key : searchMap.keySet()) {
            if (key.startsWith("spec_")) {
                boolQueryBuilder.filter(QueryBuilders.termQuery("specMap." + key.substring(5) + ".keyword", searchMap.get(key)));
            }
        }
        //价格过滤查询  前端格式 price:'0-500' ；最后项：price:'3000'
        String price = searchMap.get("price");
            if (!StringUtils.isEmpty(price)) {
            String[] strings = price.split("-");
            if (!strings[1].equalsIgnoreCase("*")) {
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").from(strings[0], true).to(strings[1], true));
            } else {
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(strings[0]));
            }
        }

        //构建过滤查询
        nativeSearchQueryBuilder.withFilter(boolQueryBuilder);

        //构建分页查询  每页显示数量固定
        Integer pageNum = 1;
        Integer pageSize = 40;
        if (!StringUtils.isEmpty(searchMap.get("pageNum"))) {
            try {
                pageNum = Integer.valueOf(searchMap.get("pageNum"));
                if (pageNum<=0){
                    pageNum = 1;
                }
            } catch (NumberFormatException e) {
                e.printStackTrace();
                pageNum = 1;
            }
        }
        nativeSearchQueryBuilder.withPageable(PageRequest.of(pageNum - 1, pageSize));

        //构建排序方式
        String sortField = searchMap.get("sortField");   //排序域名
        String sortRule = searchMap.get("sortRule");     //排序方式
        if (!StringUtils.isEmpty(sortField) && !StringUtils.isEmpty(sortRule)) {
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField)
                    .order(SortOrder.valueOf(sortRule)));
        }

        //设置高亮显示
        nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("name"));
        nativeSearchQueryBuilder.withHighlightBuilder(new HighlightBuilder().preTags("<em style='color:red'>").postTags("</em>"));

        //4.构建查询对象
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

        //5.执行查询
        AggregatedPage<SkuInfo> skuInfos = elasticsearchTemplate.queryForPage(query, SkuInfo.class, searchResultMapper);

        //获取商品分组结果
        StringTerms stringTermsCategory = (StringTerms) skuInfos.getAggregation("skuCategorygroup");
        List<String> categoryList = getStringsList(stringTermsCategory);

        //获取品牌分组结果
        StringTerms stringTermsBrand = (StringTerms) skuInfos.getAggregation("skuBrandgroup");
        List<String> brandList = getStringsList(stringTermsBrand);

        //获取规格参数分组结果
        StringTerms skuSpecgroup = (StringTerms) skuInfos.getAggregation("skuSpecgroup");
        Map<String, Set<String>> specMap = getStringSetMap(skuSpecgroup);

        //6.返回结果
        Map map = new HashMap<>();
        map.put("categoryList", categoryList);
        map.put("brandList", brandList);
        map.put("specMap", specMap);
        map.put("rows", skuInfos.getContent());
        map.put("total", skuInfos.getTotalElements());
        map.put("totalPages", skuInfos.getTotalPages());
        map.put("pageNum",  pageNum);
        map.put("pageSize", pageSize);
        return map;
    }

    /**
     * 获取规格参数的map集合
     *
     * @param stringTerms
     * @return
     */
    private Map<String, Set<String>> getStringSetMap(StringTerms stringTerms) {
        Map<String, Set<String>> specMap = new HashMap<>();
        Set<String> specList = new HashSet<>();
        if (stringTerms != null) {
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                //获取bucket的Json字符串
                String keyAsString = bucket.getKeyAsString();
                specList.add(keyAsString);
            }
        }
        //对set集合进行循环遍历，将每个值转化为map集合，再添加到map中
        for (String spec : specList) {
            Map<String, String> map = JSON.parseObject(spec, Map.class);
            //对map进行迭代获取key和value
            for (Map.Entry<String, String> entry : map.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //获取specMap中key对应的值（逻辑处理添加到对应的key的set集合中）
                Set<String> specValue = specMap.get(key);
                if (specValue == null) {
                    specValue = new HashSet<>();
                }
                //将获取的值存入到specValue集合中
                specValue.add(value);
                //将集合存到specMap中
                specMap.put(key, specValue);
            }
        }
        return specMap;

    }

    /**
     * 获取分类、品牌列表数据
     *
     * @param stringTerms
     * @return
     */
    private List<String> getStringsList(StringTerms stringTerms) {
        List<String> StringsList = new ArrayList<>();
        if (stringTerms != null) {
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();//分组的值
                StringsList.add(keyAsString);
            }
        }
        return StringsList;
    }

    /**
     * 获取品牌列表数据
     * @param stringTerms
     * @return
     *//*
    private List<String> getStringsBrandList(StringTerms stringTerms) {
        List<String> BrandList = new ArrayList<>();
        if (stringTerms != null) {
            for (StringTerms.Bucket bucket : stringTerms.getBuckets()) {
                String keyAsString = bucket.getKeyAsString();//分组的值
                BrandList.add(keyAsString);
            }
        }
        return BrandList;
    }*/
}
